home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.2 Applications 1996 May / SGI IRIX 6.2 Applications 1996 May.iso / dist / impr_dev.idb / usr / impressario / src / libspool / SLBsd.c.z / SLBsd.c
C/C++ Source or Header  |  1996-05-06  |  29KB  |  1,039 lines

  1. /**************************************************************************
  2.  *                                      *
  3.  *           Copyright (c)    1991 Silicon Graphics, Inc.          *
  4.  *            All Rights Reserved                    *
  5.  *                                      *
  6.  *       THIS    IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SGI          *
  7.  *                                      *
  8.  * The copyright notice above does not evidence any actual of intended      *
  9.  * publication of such source code, and is an unpublished work by Silicon *
  10.  * Graphics, Inc. This material contains CONFIDENTIAL INFORMATION that is *
  11.  * the property of Silicon Graphics, Inc. Any use, duplication or      *
  12.  * disclosure not specifically authorized by Silicon Graphics is strictly *
  13.  * prohibited.                                  *
  14.  *                                      *
  15.  * RESTRICTED RIGHTS LEGEND:                          *
  16.  *                                      *
  17.  * Use, duplication or disclosure by the Government is subject to      *
  18.  * restrictions as set forth in subdivision (c)(1)(ii) of the Rights in      *
  19.  * Technical Data and Computer Software clause at DFARS 52.227-7013,      *
  20.  * and/or in similar or successor clauses in the FAR, DOD or NASA FAR      *
  21.  * Supplement. Unpublished - rights reserved under the Copyright Laws of  *
  22.  * the United States. Contractor is SILICON GRAPHICS, INC., 2011 N.      *
  23.  * Shoreline Blvd., Mountain View, CA 94039-7311              *
  24.  **************************************************************************
  25.  *
  26.  * File: SLBsd.c
  27.  *
  28.  * Description: This file contains the BSD spooling system specific
  29.  *    handling functions.
  30.  *
  31.  **************************************************************************/
  32.  
  33.  
  34. #ident "$Revision: 1.7 $"
  35.  
  36.  
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <unistd.h>
  41. #include <ctype.h>
  42. #include <pwd.h>
  43. #include <sys/types.h>
  44. #include <signal.h>
  45. #include <errno.h>
  46. #include "spoolI.h"
  47.  
  48.  
  49. /* Printcap file capability keyword structure */
  50.  
  51. typedef struct {
  52.     char *key;            /* Keyword in printcap file */
  53.     char **pvar;        /* Pointer to strinct var in printer struct */
  54. } KeywordStruct;
  55.  
  56. static KeywordStruct keywords[] = {
  57.     { "lp", NULL },
  58.     { "ty", NULL },
  59.     { "rm", NULL },
  60.     { "rp", NULL },
  61.     };
  62. static int num_keywords = sizeof(keywords) / sizeof(KeywordStruct);
  63.  
  64.  
  65. /* BSD spooling directories and files */
  66.  
  67. static char *printcap_file = "/etc/printcap";
  68.  
  69. /* Print queue */
  70.  
  71. static SLQueueStruct *bsd_queue;        /* Job queue */
  72. static int num_bsd_queue;            /* Number of jobs in queue */
  73.  
  74.  
  75. /* Local functions */
  76.  
  77. static char *get_entry(FILE*);
  78. static void parse_capabilities(char*, SLPrinterStruct*);
  79. static int def_check(char*, char*);
  80. static void parse_queue(SLQueueStruct*, char*);
  81.  
  82.  
  83. /**************************************************************************
  84.  *
  85.  * Function: _SLBsdFindSpooler
  86.  *
  87.  * Description: Determines whether the BSD print scheduler is running.
  88.  *
  89.  * Parameters: none
  90.  *
  91.  * Return: 1 if the scheduler is running, 0 otherwise.
  92.  *
  93.  **************************************************************************/
  94.  
  95. int _SLBsdFindSpooler(void)
  96. {
  97.     FILE *fptr;
  98.     pid_t pid;
  99.  
  100.     /*
  101.      * Try to open lpd.lock for reading. If we cannot open the file
  102.      * assume that the scheduler is running unless we got the file does
  103.      * not exit error.
  104.      *
  105.      * Note that here we use high level file I/O because the pid is
  106.      * written as text into the lock file as opposed to System V which
  107.      * writes the pid in binary.
  108.      */
  109.     if ((fptr = fopen(SL_LPD_LOCK, "r")) == NULL) {
  110.     if (errno == ENOENT)
  111.             return 0;
  112.     return 1;
  113.     }
  114.  
  115.     /*
  116.      * When the scheduler starts it puts its pid in the lock file.
  117.      * Read this pid and use kill to determine if the process is
  118.      * around, thereby indicating that the scheduler is running. The
  119.      * only danger here is that the scheduler is not running and its
  120.      * pid has been reused. However, this case is not very likely.
  121.      */
  122.     if (fscanf(fptr, "%ld", &pid) != 1) {
  123.     (void)fclose(fptr);
  124.     return 0;
  125.     }
  126.     if (kill(pid, 0) < 0) {
  127.     if (errno == ESRCH) {           /* Indicates invalid pid */
  128.         (void)fclose(fptr);
  129.         return 0;
  130.     }
  131.     }
  132.  
  133.     (void)fclose(fptr);
  134.     return 1;
  135. }
  136.  
  137.  
  138. /**************************************************************************
  139.  *
  140.  * Function: _SLBsdGetPrinterList
  141.  *
  142.  * Description: Provides a list of the printers recognized by the
  143.  *    BSD spooling system. Any old pointers to the list become invalid
  144.  *    when this function is again called. Users must make copy of the
  145.  *    list in order to preserve old lists.
  146.  *
  147.  * Parameters:
  148.  *    printersp (O) - set to a list of available printers
  149.  *    num_printersp (O) - number of available printers in list
  150.  *
  151.  * Return: 0 is execution succeeded. -1 and SLerrno is set if an execution
  152.  *    error has occurred.
  153.  *
  154.  **************************************************************************/
  155.  
  156. int _SLBsdGetPrinterList(SLPrinterStruct *printersp[], int *num_printersp)
  157. {
  158.     FILE *fptr;
  159.     char *eptr, *sptr, *formal_name;
  160.     char *penv, *loc;
  161.     int def;
  162.     SLPrinterStruct info;
  163.     static SLPrinterStruct *bsd_printers = NULL;
  164.     static int num_bsd_printers = 0;
  165.  
  166.     /*
  167.      * Clear out and initialize the list of BSD printers
  168.      */
  169.     _SLInitPlist(&bsd_printers, &num_bsd_printers);
  170.  
  171.     /*
  172.      * Get the PRINTER environment variable setting, if any
  173.      */
  174.     penv = getenv("PRINTER");
  175.     if (penv && *penv == '\0')
  176.     penv = NULL;
  177.  
  178.     /*
  179.      * Attempt to open and read the printcap file
  180.      */
  181.     if ((fptr = fopen(printcap_file, "r")) != NULL) {
  182.  
  183.     /*
  184.      * First get a complete printcap entry
  185.      */
  186.     while ((eptr = get_entry(fptr)) != NULL) {
  187.  
  188.         /*
  189.          * Parse the capabilities part of the entry
  190.          * entry the appropriate fields of the printer_caps
  191.          * structure.
  192.          */
  193.         parse_capabilities(eptr, &info);
  194.  
  195.         /*
  196.          * Now for each printer name add a printer to the list,
  197.          * copy the printer_caps structure to the new printer
  198.          * and fill in the printer name fields. Note that the
  199.          * formal name is assumed to be the last name. Also
  200.          * note that if 'lp' or the printer name specified by the
  201.          * PRINTER environment variable is one of the names, then all
  202.          * the printer names on the line are marked as default
  203.          * printers.
  204.          */
  205.         (void)strtok_r(eptr, ":", &loc);
  206.         def = def_check(eptr, (penv) ? penv: "lp");
  207.         if ((sptr = strrchr(eptr, '|')) == NULL)
  208.         formal_name = eptr;
  209.         else
  210.         formal_name = sptr + 1;
  211.         while ((sptr = strtok_r(eptr, "|", &loc)) != NULL) {
  212.         eptr = NULL;
  213.         info.local_name = strdup(sptr);
  214.         info.formal_name = strdup(formal_name);
  215.         info.is_def = def;
  216.         info.is_class = 0;
  217.         _SLAddPrinter(&info, &bsd_printers, &num_bsd_printers);
  218.         }
  219.     }
  220.     (void)fclose(fptr);
  221.     }
  222.  
  223.     *num_printersp = num_bsd_printers;
  224.     *printersp = bsd_printers;
  225.  
  226.     return SL_NOERROR;
  227. }
  228.  
  229.  
  230. /**************************************************************************
  231.  *
  232.  * Function: _SLBsdGetPrinterInfo
  233.  *
  234.  * Description: Provides detailed information about the specified BSD
  235.  *      printer. Each time this function is called the old contents of
  236.  *      the internal info structure become invalid. If the user wishes to
  237.  *      preserve the old info, a copy must be made before calling this
  238.  *      function.
  239.  *
  240.  * Parameters:
  241.  *      printer (I) - printer whose info is wanted. Public function sets
  242.  *              this to default printer name if user specified it
  243.  *              as NULL.
  244.  *      printer_infop (O) - set to a printer information structure
  245.  *                      filled with information about the printer. Set
  246.  *                      to NULL if the specified printer does not exist.
  247.  *
  248.  * Return: 0 is execution succeeded. -1 and SLerrno is set if an execution
  249.  *      error has occurred. It is considered an error specifying a printer
  250.  *      that is not available to the spooler.
  251.  *
  252.  **************************************************************************/
  253.  
  254. int _SLBsdGetPrinterInfo(const char *printer, SLPrinterStruct **printer_infop)
  255. {
  256.     FILE *fptr;
  257.     char *eptr, *sptr, *formal_name;
  258.     char *penv, *loc;
  259.     char dup_eptr[SL_BUF_PRINTCAP];
  260.     int def, found = 0;
  261.     static SLPrinterStruct pinfo;
  262.  
  263.  
  264.     /*
  265.      * First clear any storage that may have been allocated for the struct
  266.      */
  267.     _SLInitPentry(&pinfo);
  268.  
  269.     /*
  270.      * Get the PRINTER environment variable setting, if any
  271.      */
  272.     penv = getenv("PRINTER");
  273.     if (penv && *penv == '\0')
  274.     penv = NULL;
  275.  
  276.     /*
  277.      * Attempt to open and read the printcap file
  278.      */
  279.     if ((fptr = fopen(printcap_file, "r")) != NULL) {
  280.  
  281.     /*
  282.      * First get a complete printcap entry
  283.      */
  284.     while (!found && (eptr = get_entry(fptr)) != NULL) {
  285.  
  286.         /*
  287.          * Save a copy of the entry for later parsing of 
  288.          * capabilities if this is the desired printer
  289.          */
  290.         (void)strcpy(dup_eptr, eptr);
  291.  
  292.         /*
  293.          * Now hunt for the desired printer.
  294.          */
  295.         (void)strtok_r(eptr, ":", &loc);
  296.         def = def_check(eptr, (penv) ? penv: "lp");
  297.         if ((sptr = strrchr(eptr, '|')) == NULL)
  298.         formal_name = eptr;
  299.         else
  300.         formal_name = sptr + 1;
  301.         while ((sptr = strtok_r(eptr, "|", &loc)) != NULL) {
  302.         eptr = NULL;
  303.         if (!strcmp(printer, sptr)) {
  304.                 parse_capabilities(dup_eptr, &pinfo);
  305.             pinfo.local_name = strdup(sptr);
  306.             pinfo.formal_name = strdup(formal_name);
  307.             pinfo.is_def = def;
  308.             pinfo.is_class = 0;
  309.             found = 1;
  310.             break;
  311.         }
  312.         }
  313.     }
  314.     (void)fclose(fptr);
  315.     }
  316.  
  317.     if (!found)
  318.     RETURN_ERROR(SL_ERR_BAD_PRINTER_NAME);
  319.  
  320.     *printer_infop = &pinfo;
  321.  
  322.     return SL_NOERROR;
  323. }
  324.  
  325.  
  326. /**************************************************************************
  327.  *
  328.  * Function: _SLBsdGetDefPrinterName
  329.  *
  330.  * Description: Returns the default printer name recognized by the BSD
  331.  *    spooling system.
  332.  *
  333.  * Parameters:
  334.  *    pnamep (O) - default printer or NULL if none selected
  335.  *
  336.  * Return: 0 is execution succeeded. -1 and SLerrno is set if an execution
  337.  *    error has occurred.
  338.  *
  339.  **************************************************************************/
  340.  
  341. int _SLBsdGetDefPrinterName(char **pnamep)
  342. {
  343.     FILE *fptr;
  344.     char *eptr, *loc;
  345.     static char *dname = "lp";
  346.  
  347.     /*
  348.      * Get the PRINTER environment variable setting, if any
  349.      * otherwise parse the printcap for the default, 'lp', if any
  350.      */
  351.     if ((*pnamep = getenv("PRINTER")) == NULL) {
  352.         if ((fptr = fopen(printcap_file, "r")) != NULL) {
  353.         while ((eptr = get_entry(fptr)) != NULL) {
  354.             (void)strtok_r(eptr, ":", &loc);
  355.             if (def_check(eptr, "lp")) {
  356.                 *pnamep = dname;
  357.             break;
  358.         }
  359.         }
  360.         (void)fclose(fptr);
  361.         }
  362.     }
  363.  
  364.     /*
  365.      * If no def printer make sure pointer is NULL and
  366.      * return error to the user
  367.      */
  368.     if (*pnamep == NULL || *pnamep[0] == '\0') {
  369.     *pnamep = NULL;
  370.     RETURN_ERROR(SL_ERR_NO_DEF_PRINTER);
  371.     }
  372.  
  373.     return SL_NOERROR;
  374. }
  375.  
  376.  
  377. /**************************************************************************
  378.  *
  379.  * Function: _SLBsdGetPrinterSettings
  380.  *
  381.  * Description: Reads the spooler and printer option settings.
  382.  *
  383.  *    Currently, there are no tools which save BSD spooler or printer
  384.  *    specific settings. This function returns the default settings.
  385.  *
  386.  * Parameters:
  387.  *      printer (I) - printer whose settings are wanted.
  388.  *      settingsp (O) - set to a printer settings structure
  389.  *                      filled with the currently saved printer settings.
  390.  *                      information about the printer.
  391.  *
  392.  * Return: 0 is execution succeeded. -1 and SLerrno is set if an execution
  393.  *      error has occurred.
  394.  *
  395.  **************************************************************************/
  396. /* ARGSUSED */
  397.  
  398. int _SLBsdGetPrinterSettings(const char *printer,
  399.                     SLSettingsStruct **settingsp)
  400. {
  401.     static SLSettingsStruct settings;
  402.  
  403.     /*
  404.      * Fill the settings structure with default values
  405.      * and return it.
  406.      */
  407.     settings.copy = 1;
  408.     settings.mail = 0;
  409.     settings.title = NULL;
  410.     settings.options = NULL;
  411.  
  412.     *settingsp = &settings;
  413.  
  414.     return SL_NOERROR;
  415. }
  416.  
  417.  
  418. /**************************************************************************
  419.  *
  420.  * Function: _SLBsdSubmitJob
  421.  *
  422.  * Description: Submits a job for printing using the BSD spooler.
  423.  *
  424.  * Parameters:
  425.  *      job_source (I) - union describing the print job source (eg.
  426.  *        filename, fd, etc.)
  427.  *    printer (I) - printer on which to print job. Public function
  428.  *        fills this with the default printer if the
  429.  *            user specified it as NULL.
  430.  *    num_copies (I) - number of copies
  431.  *    copy (I) - Copy flag. If 1 then file is copied to spooling dir. If
  432.  *            0 a link is created.
  433.  *      mail (I) - Mail flag. If 1 then mail is sent on job print completion.
  434.  *              If 0, no mail is sent.
  435.  *    title (I) - title to appear on banner page.
  436.  *    options (I) - string of spooling system/printer specific options.
  437.  *            Set to NULL if none.
  438.  *    job_idp (O) - print job ID
  439.  *
  440.  * Return: 0 if no error. -1 and SLerrno set if error.
  441.  *                                                          
  442.  **************************************************************************/
  443.  
  444. int _SLBsdSubmitJob(SLJobSourceUnion *job_source, const char *printer,
  445.                 int num_copies, int copy, int mail,
  446.                 const char *title, const char *options,
  447.                 char **job_idp)
  448. {
  449.     char cmd_buf[SL_BUFSIZ], buf[SL_BUFSIZ];
  450.     char *t_ptr;
  451.     char *b_ptr;
  452.  
  453.     /*
  454.      * Start filling the command buffer with parameters. Start with
  455.      * the printing command and the destination printer name
  456.      */
  457.     (void)sprintf(cmd_buf, "%s -P%s", SL_CMD_LPR, printer);
  458.  
  459.     /* Number of copies */
  460.     if (num_copies > 1) {
  461.     (void)sprintf(buf, " -#%d", num_copies);
  462.     (void)strcat(cmd_buf, buf);
  463.     }
  464.  
  465.     /* Don't copy file to spool dir */
  466.     if (!copy)
  467.     (void)strcat(cmd_buf, " -s");
  468.  
  469.     /* Mail sent on completion */
  470.     if (mail)
  471.     (void)strcat(cmd_buf, " -m");
  472.  
  473.  
  474.     /* Banner page title --  handle a char at a time to handle case of
  475.      * characters that the shell will interpret
  476.      */
  477.     if (title) {
  478.         for (t_ptr = (char *)title, b_ptr = buf; *t_ptr; t_ptr++) {
  479.            if ( !isalnum((int) *t_ptr) && !isspace((int) *t_ptr) ) {
  480.               *b_ptr++ = '\\';   /* Escape these */
  481.            }
  482.            *b_ptr++ = *t_ptr;
  483.            if ((b_ptr - buf) == SL_BUFSIZ-10) break; /* Stay in bounds */
  484.         }
  485.         *b_ptr = '\0';
  486.  
  487.         (void)strcat(cmd_buf, " -J\"");
  488.     /* (void)sprintf(buf, " -J '%s'", title); */
  489.         (void)strcat(cmd_buf, buf);
  490.         (void)strcat(cmd_buf, "\"");
  491.     }
  492.  
  493.     /* Printer/Spooler specific options */
  494.     if (options) {
  495.     (void)sprintf(buf, " %s", options);
  496.     (void)strcat(cmd_buf, buf);
  497.     }
  498.  
  499.     /* Add the file(s) to print, if appropriate */
  500.     if (job_source->type == SL_JOB_FILENAME) {
  501.         (void)sprintf(buf, " %s", job_source->filename_job.filename);
  502.         (void)strcat(cmd_buf, buf);
  503.     }
  504.     
  505.     /* Lastly add the sh output redirection */
  506.     (void)sprintf(buf, " %s", SL_SH_REDIRECT);
  507.     (void)strcat(cmd_buf, buf);
  508.  
  509.     /*
  510.      * Issue the command. Note that BSD does not return a
  511.      * job ID so we send back NULL.
  512.      */
  513.     if (_SLExec(job_source, cmd_buf, SL_FALSE, NULL) != 0) {
  514.     RETURN_ERROR(SL_ERR_SPOOLER_ERROR);
  515.     }
  516.     *job_idp = NULL;
  517.  
  518.     return SL_NOERROR;
  519. }
  520.  
  521.  
  522. /**************************************************************************
  523.  *
  524.  * Function: _SLBsdCancelJob
  525.  *
  526.  * Description: Sends a cancel print job request to the BSD spooling
  527.  *    system. Note that there is no confirmation that a print job has
  528.  *    actually been canceled.
  529.  *
  530.  * Parameters:
  531.  *    job_id (I) - print job ID(s) of the job(s) that are to be canceled.
  532.  *    printer (I) - printer on which the job resides. If NULL the 
  533.  *              current default printer is used.
  534.  *
  535.  * Return: 0 is execution succeeded. -1 and SLerrno is set if an execution
  536.  *    error has occurred.
  537.  *
  538.  **************************************************************************/
  539.  
  540. int _SLBsdCancelJob(const char *job_id, const char *printer)
  541. {
  542.     char cmd_buf[SL_BUFSIZ];
  543.     char *def_printer;
  544.     int rv;
  545.  
  546.     /*
  547.      * If no printer specified, use default.
  548.      * If printer specified sanity check the name.
  549.      */
  550.     if (!printer) {
  551.         if ((rv = _SLBsdGetDefPrinterName(&def_printer)) < 0)
  552.             return rv;
  553.         printer = def_printer;
  554.     } else if (_SLIsEmpty(printer))
  555.     RETURN_ERROR(SL_ERR_BAD_PRINTER_NAME);
  556.  
  557.     /*
  558.      * Fill the command buffer with parameters
  559.      *        lprm + Printer + Job ID(s) + sh output direction
  560.      */
  561.     (void)sprintf(cmd_buf, "%s -P%s %s %s",
  562.             SL_CMD_LPRM,
  563.             printer,
  564.             job_id,
  565.             SL_SH_REDIRECT);
  566.  
  567.     /*
  568.      * Issue the command
  569.      */
  570.     if (_SLExec(NULL, cmd_buf, SL_FALSE, NULL) != 0) 
  571.     RETURN_ERROR(SL_ERR_SPOOLER_ERROR);
  572.  
  573.     return SL_NOERROR;
  574. }
  575.  
  576.  
  577. /**************************************************************************
  578.  *
  579.  * Function: _SLBsdGetSpoolerState
  580.  *
  581.  * Description: Returns the state of the specified spooling function for
  582.  *    the BSD spooling system.
  583.  *
  584.  * Parameters:
  585.  *    printer (I) - printer whose spooler state to query.
  586.  *    function (I) - spooling function whose state to query (one of
  587.  *                   SL_PRINTING or SL_QUEUEING).
  588.  *    statep (O) - state of the spooling function (one of SL_ENABLED or
  589.  *                 SL_DISABLED).
  590.  *
  591.  * Return: 0 is execution succeeded. -1 and SLerrno is set if an execution
  592.  *    error has occurred.
  593.  *
  594.  **************************************************************************/
  595.  
  596. int _SLBsdGetSpoolerState(const char *printer, int function, int *statep)
  597. {
  598.     char cmd_buf[SL_BUFSIZ];
  599.  
  600.     /*
  601.      * Fill the command buffer with parameters
  602.      *        lpc + status + printer + sh output redirection
  603.      */
  604.     (void)sprintf(cmd_buf, "%s status %s %s",
  605.                 SL_CMD_LPC,
  606.                 printer,
  607.                 SL_SH_REDIRECT);
  608.  
  609.     /*
  610.      * Issue the command
  611.      */
  612.     if (_SLExec(NULL, cmd_buf, SL_FALSE, NULL) != 0)
  613.     RETURN_ERROR(SL_ERR_SPOOLER_ERROR);
  614.  
  615.     /*
  616.      * Parse out the state information
  617.      */
  618.     if (_SLspooler_nout >= 3) {
  619.     if (function == SL_PRINTING) {
  620.         if (strstr(_SLspooler_out_buf[2], "disabled") != NULL)
  621.         *statep = SL_DISABLED;
  622.         else if (strstr(_SLspooler_out_buf[2], "enabled") != NULL)
  623.         *statep = SL_ENABLED;
  624.         else {
  625.         _SLspooler_exit = 1;    /* Stupid System V returned 0 */
  626.         RETURN_ERROR(SL_ERR_SPOOLER_ERROR);
  627.         }
  628.     } else {        /* Queueing */
  629.         if (strstr(_SLspooler_out_buf[1], "disabled") != NULL)
  630.         *statep = SL_DISABLED;
  631.         else if (strstr(_SLspooler_out_buf[1], "enabled") != NULL)
  632.         *statep = SL_ENABLED;
  633.         else {
  634.         _SLspooler_exit = 1;    /* Stupid System V returned 0 */
  635.         RETURN_ERROR(SL_ERR_SPOOLER_ERROR);
  636.         }
  637.     }
  638.     } else
  639.     RETURN_ERROR(SL_ERR_NO_STATE);
  640.  
  641.     return SL_NOERROR;
  642. }
  643.  
  644.  
  645. /**************************************************************************
  646.  *
  647.  * Function: _SLBsdSetSpoolerState
  648.  *
  649.  * Description: Sets the state of the specified spooling function for the
  650.  *    BSD spooling system.
  651.  *
  652.  * Parameters:
  653.  *    printer (I) - printer whose spooler state to set.
  654.  *    function (I) - spooling function whose state to set (one of
  655.  *                   SL_PRINTING or SL_QUEUEING).
  656.  *    state (I) - state to set for the spooling function (one of
  657.  *                 SL_ENABLED or SL_DISABLED).
  658.  *
  659.  * Return: 0 is execution succeeded. -1 and SLerrno is set if an execution
  660.  *    error has occurred.
  661.  *
  662.  **************************************************************************/
  663.  
  664. int _SLBsdSetSpoolerState(const char *printer, int function, int state)
  665. {
  666.     char cmd_buf[SL_BUFSIZ], buf[SL_BUFSIZ];
  667.  
  668.     /*
  669.      * Make sure that we are root since all spooler state
  670.      * operations are priveleged in BSD. Note that I check uid
  671.      * and not euid. This is because the underlying BSD command
  672.      * check uid not euid. I must do what BSD does or you will
  673.      * pass my test and fail theirs.
  674.      */
  675.     if (getuid() != 0)
  676.         RETURN_ERROR(SL_ERR_PRIVILEGE);
  677.  
  678.     /*
  679.      * Start filling the command buffer with parameters
  680.      */
  681.     (void)sprintf(cmd_buf, "%s ", SL_CMD_LPC);
  682.     if (function == SL_PRINTING) {
  683.     (void)strcat(cmd_buf, (state == SL_ENABLED) ? "start": "stop");
  684.     } else {    /* Queueing */
  685.     (void)strcat(cmd_buf, (state == SL_ENABLED) ? "enable": "disable");
  686.     }
  687.  
  688.     /* Add the printer and sh output redirection */
  689.     (void)sprintf(buf, " %s %s", printer, SL_SH_REDIRECT);
  690.     (void)strcat(cmd_buf, buf);
  691.  
  692.     /*
  693.      * Issue the command
  694.      */
  695.     if (_SLExec(NULL, cmd_buf, SL_FALSE, NULL) != 0)
  696.     RETURN_ERROR(SL_ERR_SPOOLER_ERROR);
  697.  
  698.     /*
  699.      * BSD has a problem with reporting a non-zero exit status for
  700.      * errors such as unknown printers. The heuristic here is to check
  701.      * for the phrase "unkown printer" in the rist line of the return
  702.      * string.
  703.      */
  704.     if (_SLspooler_nout) {
  705.     if (strstr(*_SLspooler_out_buf, "unknown printer")) {
  706.         _SLspooler_exit = 1;    /* Stupid BSD returned 0 */
  707.         RETURN_ERROR(SL_ERR_SPOOLER_ERROR);
  708.     }
  709.     }
  710.  
  711.     return SL_NOERROR;
  712. }
  713.  
  714.  
  715. /**************************************************************************
  716.  *
  717.  * Function: _SLBsdGetQueue
  718.  *
  719.  * Description: Returns the job queue for the specified printer under
  720.  *    the BSD spooling system.
  721.  *
  722.  * Parameters:
  723.  *    printer_info (I) - printer structure. Cannot be NULL.
  724.  *    queue_type (I) - not used for the BSD spooler.
  725.  *    queuep (O) - print queue entries.
  726.  *    num_queuep (O) - number of entries in the queue.
  727.  *
  728.  * Return: 0 is execution succeeded. -1 and SLerrno is set if an execution
  729.  *    error has occurred.
  730.  *
  731.  **************************************************************************/
  732. /* ARGSUSED */
  733.  
  734. int _SLBsdGetQueue(const SLPrinterStruct *printer_info, int queue_type,
  735.                 SLQueueStruct *queuep[], int *num_queuep)
  736. {
  737.     char cmd_buf[SL_BUFSIZ];
  738.     int i;
  739.     SLQueueStruct *qentry;
  740.  
  741.     /*
  742.      * Clear out and initialize the BSD queue
  743.      */
  744.     _SLInitQueue(&bsd_queue, &num_bsd_queue);
  745.  
  746.     /*
  747.      * Form the queue command and issue it
  748.      */
  749.     (void)sprintf(cmd_buf, "%s -P%s %s",
  750.             SL_CMD_LPQ,
  751.             printer_info->local_name,
  752.             SL_SH_REDIRECT);
  753.     if (_SLExec(NULL, cmd_buf, SL_FALSE, NULL) != 0)
  754.     RETURN_ERROR(SL_ERR_SPOOLER_ERROR);
  755.  
  756.     /*
  757.      * Now parse the output to form the queue. We look for the
  758.      * keyword '1st' to mark the start of the queue info
  759.      */
  760.     for (i = 0; i < _SLspooler_nout; i++) {
  761.     if (strstr(_SLspooler_out_buf[i], "1st")) {
  762.         break;
  763.     }
  764.     }
  765.     for (; i < _SLspooler_nout; i++) {
  766.     if (_SLIsEmpty(_SLspooler_out_buf[i]))
  767.         break;
  768.     qentry = _SLAddQueue(&bsd_queue, &num_bsd_queue);
  769.     parse_queue(qentry, _SLspooler_out_buf[i]);
  770.     qentry->is_local = 1;    /* Entries can be considered local on BSD */
  771.     }
  772.  
  773.     *num_queuep = num_bsd_queue;
  774.     *queuep = bsd_queue;
  775.  
  776.     return SL_NOERROR;
  777. }
  778.  
  779.  
  780. #ifdef _SL_FASTPATH
  781. /**************************************************************************
  782.  *
  783.  * Function: _SLBsdSupportsFastJob
  784.  *
  785.  * Description:
  786.  *      Find out whether a printer supports fast print jobs
  787.  *    For now, fast print jobs are not supported on BSD spoolers.
  788.  *
  789.  * Parameters:
  790.  *      printer  printer to find out if supports fast jobs
  791.  *
  792.  * Return: non-zero if fast job supported, 0 otherwise
  793.  *
  794.  **************************************************************************/
  795. /* ARGSUSED */
  796.  
  797. int _SLBsdSupportsFastJob(const char *printer)
  798. {
  799.     return SL_FALSE;
  800. }
  801. #endif /* _SL_FASTPATH */
  802.  
  803.  
  804. /**************************************************************************
  805.  *
  806.  * Function: _SLBsdFindUserName
  807.  *
  808.  * Description: Determines the user name in the same manner as the BSD
  809.  *    spooling system.
  810.  *
  811.  * Parameters: none
  812.  *
  813.  * Return: Pointer to user name. The storage for username is static and
  814.  *    the returned value should be copied if it is not going to be
  815.  *    used immediately after the call.
  816.  *
  817.  **************************************************************************/
  818.  
  819. char* _SLBsdFindUserName(void)
  820. {
  821.     static char *unknown = "Unknown";
  822.     struct passwd *pw;
  823.  
  824.     return ((pw = getpwuid(getuid())) == NULL) ? unknown: pw->pw_name;
  825. }
  826.  
  827.  
  828. /*
  829.  ==========================================================================
  830.                          LOCAL FUNCTIONS
  831.  ==========================================================================
  832. */
  833.  
  834.  
  835. /**************************************************************************
  836.  *
  837.  * Function: get_entry
  838.  *
  839.  * Description: Returns a pointer to a printcap file entry. The file
  840.  *    is searched for the next printcap entry. Comments and blank lines
  841.  *    are skipped. Coninuation characters are stripped out and all
  842.  *    lines comprising the entry are reassembled into one line.
  843.  *
  844.  *    Per BSD a printcap entry can be no larger than 1024 characters
  845.  *    and comments must sit on lines by themselves.
  846.  *
  847.  * Parameters: 
  848.  *    fptr (I) - pointer to an open printcap file.
  849.  *
  850.  * Return: Pointer to the next entry in the file or NULL if no more
  851.  *    entries can be found.
  852.  *
  853.  **************************************************************************/
  854.  
  855. static char *get_entry(FILE *fptr)
  856. {
  857.     static char entry[SL_BUF_PRINTCAP];
  858.     char buf[SL_SML_BUFSIZ], *bptr, *cptr;
  859.     char *eptr = NULL;
  860.  
  861.     /*
  862.      * Look for an entry
  863.      */
  864.     *entry = '\0';
  865.     while (fgets(buf, SL_SML_BUFSIZ, fptr) != NULL) {
  866.     if (*buf == '\n' || strchr(buf, '#'))
  867.         continue;
  868.     buf[strlen(buf) - 1] = '\0';
  869.     if ((bptr = _SLSkipSpace(buf)) == NULL)
  870.         continue;
  871.     eptr = strcat(entry, bptr);
  872.     if ((cptr = strrchr(entry, '\\')) == NULL)
  873.         break;
  874.     *cptr = '\0';
  875.     }
  876.  
  877.     return eptr;
  878. }
  879.  
  880.  
  881. /**************************************************************************
  882.  *
  883.  * Function: parse_capabilities
  884.  *
  885.  * Description: Parses the specified printcap entry for the capabilities
  886.  *    relevant to the printer structure. The name fields in the entry
  887.  *    are not parsed. All fields in printer structure are initialized.
  888.  *
  889.  *    This routine assumes that entries that match our keywords will
  890.  *    appear as keyword=value with no leading whitespace, no whitespace
  891.  *    between the keyword, '=', or value.
  892.  *
  893.  * Parameters: 
  894.  *    eptr (I) - pointer to a printcap entry
  895.  *    printer (I) - printer structure to fill
  896.  *
  897.  * Return: none
  898.  *
  899.  **************************************************************************/
  900.  
  901. static void parse_capabilities(char *eptr, SLPrinterStruct *printer)
  902. {
  903.     char entry[SL_BUF_PRINTCAP], *sptr;
  904.     char *vptr, *loc;
  905.     int i;
  906.  
  907.     /*
  908.      * Initialize the printer struct
  909.      */
  910.     printer->local_name = NULL;
  911.     printer->formal_name = NULL;
  912.     printer->type = NULL;
  913.     printer->dev = NULL;
  914.     printer->is_def = 0;
  915.     printer->is_networked = 0;
  916.     printer->remote_host = NULL;
  917.     printer->remote_name = NULL;
  918.     printer->network_type = NULL;
  919.  
  920.     /*
  921.      * Initialize keyword structure
  922.      */
  923.     keywords[0].pvar = &printer->dev;
  924.     keywords[1].pvar = &printer->type;
  925.     keywords[2].pvar = &printer->remote_host;
  926.     keywords[3].pvar = &printer->remote_name;
  927.  
  928.     (void)strcpy(entry, eptr);
  929.     (void)strtok_r(entry, ":", &loc);
  930.     while ((sptr = strtok_r(NULL, ":", &loc)) != NULL) {
  931.     /*
  932.      * Search the keyword list
  933.      */
  934.     for (i = 0; i < num_keywords; i++) {
  935.         if (!strncmp(sptr, keywords[i].key, 2)) {
  936.         vptr = sptr + 3;
  937.         if (*vptr)
  938.             *keywords[i].pvar = strdup(vptr);
  939.         break;
  940.         }
  941.     }
  942.     }
  943.  
  944.     /*
  945.      * If the remmote_host field has been filled, then
  946.      * the printer is networked
  947.      */
  948.     if (printer->remote_host) {
  949.     printer->is_networked = 1;
  950.     printer->network_type = strdup("bsd");
  951.     }
  952.  
  953.     /*
  954.      * If the type field did not get filled mark it Unknown
  955.      */
  956.     if (!printer->type)
  957.     printer->type = strdup("Unknown");
  958. }
  959.  
  960.  
  961. /**************************************************************************
  962.  *
  963.  * Function: def_check
  964.  *
  965.  * Description: Checks for the presence of the specified printer name on
  966.  *    a printercap name line.
  967.  *
  968.  * Parameters: 
  969.  *    nptr (I) - printer name section of a printcap entry. Trailing ':'
  970.  *           has been removed.
  971.  *    def (I) - default printer name.
  972.  *
  973.  * Return: 0 if 'lp' not found. 1 if found.
  974.  *
  975.  **************************************************************************/
  976.  
  977. static int def_check(char *nptr, char *def)
  978. {
  979.     char buf[SL_SML_BUFSIZ];
  980.     char *sptr, *loc;
  981.  
  982.     if (strstr(nptr, def) == NULL)
  983.     return 0;
  984.     (void)strcpy(buf, nptr);
  985.     sptr = buf;
  986.     while ((sptr = strtok_r(sptr, "|", &loc)) != NULL) {
  987.     if (strcmp(sptr, def))
  988.         return 1;
  989.     sptr = NULL;
  990.     }
  991.     return 0;
  992. }
  993.  
  994. /**************************************************************************
  995.  *
  996.  * Function: parse_queue
  997.  *
  998.  * Description: Parses an lpq queue output string and places the
  999.  *    appropriate info in the specified queue structure.
  1000.  *
  1001.  * Parameters:
  1002.  *    entry (O) - queue structure to be filled
  1003.  *    line (I) - lpq output line to parse
  1004.  *
  1005.  * Return: none
  1006.  *
  1007.  **************************************************************************/
  1008. static void parse_queue(SLQueueStruct *entry, char *line)
  1009. {
  1010.     char job_id[SL_SML_BUFSIZ], owner[SL_SML_BUFSIZ];
  1011.     char *sptr;
  1012.  
  1013.     /*
  1014.      * Initialize all fields in case not everything gets filled
  1015.      */
  1016.     entry->job_id = entry->username = NULL;
  1017.     entry->size = entry->time_stamp = 0;
  1018.     entry->title = NULL;
  1019.  
  1020.     /*
  1021.      * Init buffers in case not scanned
  1022.      */
  1023.     *job_id = *owner = '\0';
  1024.  
  1025.     /*
  1026.      * Parse the line
  1027.      */
  1028.     (void)sscanf(line, "%*s %s %s", owner, job_id);
  1029.     if (*job_id)
  1030.     entry->job_id = strdup(job_id);
  1031.     if (*owner)
  1032.     entry->username = strdup(owner);
  1033.     if ((sptr = strstr(line, "byte")) != NULL) {
  1034.     for (sptr -= 2; isdigit(*sptr); sptr--)
  1035.         ;
  1036.     entry->size = atoi(++sptr);
  1037.     }
  1038. }
  1039.